home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / intl / plural.y < prev    next >
Encoding:
Lex Description  |  2003-05-19  |  8.2 KB  |  414 lines

  1. %{
  2. /* Expression parsing for plural form selection.
  3.    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
  4.    Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
  5.  
  6.    This program is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU Library General Public License as published
  8.    by the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.    Library General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU Library General Public
  17.    License along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  19.    USA.  */
  20.  
  21. /* The bison generated parser uses alloca.  AIX 3 forces us to put this
  22.    declaration at the beginning of the file.  The declaration in bison's
  23.    skeleton file comes too late.  This must come before <config.h>
  24.    because <config.h> may include arbitrary system headers.  */
  25. #if defined _AIX && !defined __GNUC__
  26.  #pragma alloca
  27. #endif
  28.  
  29. #ifdef HAVE_CONFIG_H
  30. # include <config.h>
  31. #endif
  32.  
  33. #include <stdlib.h>
  34. #include "gettextP.h"
  35.  
  36. /* Names for the libintl functions are a problem.  They must not clash
  37.    with existing names and they should follow ANSI C.  But this source
  38.    code is also used in GNU C Library where the names have a __
  39.    prefix.  So we have to make a difference here.  */
  40. #ifdef _LIBC
  41. # define FREE_EXPRESSION __gettext_free_exp
  42. #else
  43. # define FREE_EXPRESSION gettext_free_exp__
  44. # define __gettextparse gettextparse__
  45. #endif
  46.  
  47. #define YYLEX_PARAM    &((struct parse_args *) arg)->cp
  48. #define YYPARSE_PARAM    arg
  49. %}
  50. %pure_parser
  51. %expect 10
  52.  
  53. %union {
  54.   unsigned long int num;
  55.   enum operator op;
  56.   struct expression *exp;
  57. }
  58.  
  59. %{
  60. /* Prototypes for local functions.  */
  61. static struct expression *new_exp PARAMS ((int nargs, enum operator op,
  62.                        struct expression * const *args));
  63. static inline struct expression *new_exp_0 PARAMS ((enum operator op));
  64. static inline struct expression *new_exp_1 PARAMS ((enum operator op,
  65.                            struct expression *right));
  66. static struct expression *new_exp_2 PARAMS ((enum operator op,
  67.                          struct expression *left,
  68.                          struct expression *right));
  69. static inline struct expression *new_exp_3 PARAMS ((enum operator op,
  70.                            struct expression *bexp,
  71.                            struct expression *tbranch,
  72.                            struct expression *fbranch));
  73. static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
  74. static void yyerror PARAMS ((const char *str));
  75.  
  76. /* Allocation of expressions.  */
  77.  
  78. static struct expression *
  79. new_exp (nargs, op, args)
  80.      int nargs;
  81.      enum operator op;
  82.      struct expression * const *args;
  83. {
  84.   int i;
  85.   struct expression *newp;
  86.  
  87.   /* If any of the argument could not be malloc'ed, just return NULL.  */
  88.   for (i = nargs - 1; i >= 0; i--)
  89.     if (args[i] == NULL)
  90.       goto fail;
  91.  
  92.   /* Allocate a new expression.  */
  93.   newp = (struct expression *) malloc (sizeof (*newp));
  94.   if (newp != NULL)
  95.     {
  96.       newp->nargs = nargs;
  97.       newp->operation = op;
  98.       for (i = nargs - 1; i >= 0; i--)
  99.     newp->val.args[i] = args[i];
  100.       return newp;
  101.     }
  102.  
  103.  fail:
  104.   for (i = nargs - 1; i >= 0; i--)
  105.     FREE_EXPRESSION (args[i]);
  106.  
  107.   return NULL;
  108. }
  109.  
  110. static inline struct expression *
  111. new_exp_0 (op)
  112.      enum operator op;
  113. {
  114.   return new_exp (0, op, NULL);
  115. }
  116.  
  117. static inline struct expression *
  118. new_exp_1 (op, right)
  119.      enum operator op;
  120.      struct expression *right;
  121. {
  122.   struct expression *args[1];
  123.  
  124.   args[0] = right;
  125.   return new_exp (1, op, args);
  126. }
  127.  
  128. static struct expression *
  129. new_exp_2 (op, left, right)
  130.      enum operator op;
  131.      struct expression *left;
  132.      struct expression *right;
  133. {
  134.   struct expression *args[2];
  135.  
  136.   args[0] = left;
  137.   args[1] = right;
  138.   return new_exp (2, op, args);
  139. }
  140.  
  141. static inline struct expression *
  142. new_exp_3 (op, bexp, tbranch, fbranch)
  143.      enum operator op;
  144.      struct expression *bexp;
  145.      struct expression *tbranch;
  146.      struct expression *fbranch;
  147. {
  148.   struct expression *args[3];
  149.  
  150.   args[0] = bexp;
  151.   args[1] = tbranch;
  152.   args[2] = fbranch;
  153.   return new_exp (3, op, args);
  154. }
  155.  
  156. %}
  157.  
  158. /* This declares that all operators have the same associativity and the
  159.    precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
  160.    There is no unary minus and no bitwise operators.
  161.    Operators with the same syntactic behaviour have been merged into a single
  162.    token, to save space in the array generated by bison.  */
  163. %right '?'        /*   ?        */
  164. %left '|'        /*   ||        */
  165. %left '&'        /*   &&        */
  166. %left EQUOP2        /*   == !=    */
  167. %left CMPOP2        /*   < > <= >=    */
  168. %left ADDOP2        /*   + -    */
  169. %left MULOP2        /*   * / %    */
  170. %right '!'        /*   !        */
  171.  
  172. %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
  173. %token <num> NUMBER
  174. %type <exp> exp
  175.  
  176. %%
  177.  
  178. start:      exp
  179.       {
  180.         if ($1 == NULL)
  181.           YYABORT;
  182.         ((struct parse_args *) arg)->res = $1;
  183.       }
  184.     ;
  185.  
  186. exp:      exp '?' exp ':' exp
  187.       {
  188.         $$ = new_exp_3 (qmop, $1, $3, $5);
  189.       }
  190.     | exp '|' exp
  191.       {
  192.         $$ = new_exp_2 (lor, $1, $3);
  193.       }
  194.     | exp '&' exp
  195.       {
  196.         $$ = new_exp_2 (land, $1, $3);
  197.       }
  198.     | exp EQUOP2 exp
  199.       {
  200.         $$ = new_exp_2 ($2, $1, $3);
  201.       }
  202.     | exp CMPOP2 exp
  203.       {
  204.         $$ = new_exp_2 ($2, $1, $3);
  205.       }
  206.     | exp ADDOP2 exp
  207.       {
  208.         $$ = new_exp_2 ($2, $1, $3);
  209.       }
  210.     | exp MULOP2 exp
  211.       {
  212.         $$ = new_exp_2 ($2, $1, $3);
  213.       }
  214.     | '!' exp
  215.       {
  216.         $$ = new_exp_1 (lnot, $2);
  217.       }
  218.     | 'n'
  219.       {
  220.         $$ = new_exp_0 (var);
  221.       }
  222.     | NUMBER
  223.       {
  224.         if (($$ = new_exp_0 (num)) != NULL)
  225.           $$->val.num = $1;
  226.       }
  227.     | '(' exp ')'
  228.       {
  229.         $$ = $2;
  230.       }
  231.     ;
  232.  
  233. %%
  234.  
  235. void
  236. internal_function
  237. FREE_EXPRESSION (exp)
  238.      struct expression *exp;
  239. {
  240.   if (exp == NULL)
  241.     return;
  242.  
  243.   /* Handle the recursive case.  */
  244.   switch (exp->nargs)
  245.     {
  246.     case 3:
  247.       FREE_EXPRESSION (exp->val.args[2]);
  248.       /* FALLTHROUGH */
  249.     case 2:
  250.       FREE_EXPRESSION (exp->val.args[1]);
  251.       /* FALLTHROUGH */
  252.     case 1:
  253.       FREE_EXPRESSION (exp->val.args[0]);
  254.       /* FALLTHROUGH */
  255.     default:
  256.       break;
  257.     }
  258.  
  259.   free (exp);
  260. }
  261.  
  262.  
  263. static int
  264. yylex (lval, pexp)
  265.      YYSTYPE *lval;
  266.      const char **pexp;
  267. {
  268.   const char *exp = *pexp;
  269.   int result;
  270.  
  271.   while (1)
  272.     {
  273.       if (exp[0] == '\0')
  274.     {
  275.       *pexp = exp;
  276.       return YYEOF;
  277.     }
  278.  
  279.       if (exp[0] != ' ' && exp[0] != '\t')
  280.     break;
  281.  
  282.       ++exp;
  283.     }
  284.  
  285.   result = *exp++;
  286.   switch (result)
  287.     {
  288.     case '0': case '1': case '2': case '3': case '4':
  289.     case '5': case '6': case '7': case '8': case '9':
  290.       {
  291.     unsigned long int n = result - '0';
  292.     while (exp[0] >= '0' && exp[0] <= '9')
  293.       {
  294.         n *= 10;
  295.         n += exp[0] - '0';
  296.         ++exp;
  297.       }
  298.     lval->num = n;
  299.     result = NUMBER;
  300.       }
  301.       break;
  302.  
  303.     case '=':
  304.       if (exp[0] == '=')
  305.     {
  306.       ++exp;
  307.       lval->op = equal;
  308.       result = EQUOP2;
  309.     }
  310.       else
  311.     result = YYERRCODE;
  312.       break;
  313.  
  314.     case '!':
  315.       if (exp[0] == '=')
  316.     {
  317.       ++exp;
  318.       lval->op = not_equal;
  319.       result = EQUOP2;
  320.     }
  321.       break;
  322.  
  323.     case '&':
  324.     case '|':
  325.       if (exp[0] == result)
  326.     ++exp;
  327.       else
  328.     result = YYERRCODE;
  329.       break;
  330.  
  331.     case '<':
  332.       if (exp[0] == '=')
  333.     {
  334.       ++exp;
  335.       lval->op = less_or_equal;
  336.     }
  337.       else
  338.     lval->op = less_than;
  339.       result = CMPOP2;
  340.       break;
  341.  
  342.     case '>':
  343.       if (exp[0] == '=')
  344.     {
  345.       ++exp;
  346.       lval->op = greater_or_equal;
  347.     }
  348.       else
  349.     lval->op = greater_than;
  350.       result = CMPOP2;
  351.       break;
  352.  
  353.     case '*':
  354.       lval->op = mult;
  355.       result = MULOP2;
  356.       break;
  357.  
  358.     case '/':
  359.       lval->op = divide;
  360.       result = MULOP2;
  361.       break;
  362.  
  363.     case '%':
  364.       lval->op = module;
  365.       result = MULOP2;
  366.       break;
  367.  
  368.     case '+':
  369.       lval->op = plus;
  370.       result = ADDOP2;
  371.       break;
  372.  
  373.     case '-':
  374.       lval->op = minus;
  375.       result = ADDOP2;
  376.       break;
  377.  
  378.     case 'n':
  379.     case '?':
  380.     case ':':
  381.     case '(':
  382.     case ')':
  383.       /* Nothing, just return the character.  */
  384.       break;
  385.  
  386.     case ';':
  387.     case '\n':
  388.     case '\0':
  389.       /* Be safe and let the user call this function again.  */
  390.       --exp;
  391.       result = YYEOF;
  392.       break;
  393.  
  394.     default:
  395.       result = YYERRCODE;
  396. #if YYDEBUG != 0
  397.       --exp;
  398. #endif
  399.       break;
  400.     }
  401.  
  402.   *pexp = exp;
  403.  
  404.   return result;
  405. }
  406.  
  407.  
  408. static void
  409. yyerror (str)
  410.      const char *str;
  411. {
  412.   /* Do nothing.  We don't print error messages here.  */
  413. }
  414.